/**
 * PPH系统内存优化和自动清理脚本
 * 
 * 功能：
 * 1. 监控内存使用情况
 * 2. 自动清理缓存和临时文件
 * 3. 强制垃圾回收
 * 4. 日志文件清理
 * 5. 内存泄漏检测
 */

const fs = require('fs');
const path = require('path');
const { exec } = require('child_process');
const util = require('util');

const execAsync = util.promisify(exec);

class MemoryOptimizer {
  constructor() {
    this.deployDir = path.join(__dirname, '..');
    this.logDir = path.join(this.deployDir, 'app', 'logs');
    this.tempDir = path.join(this.deployDir, 'app', 'backend', 'uploads', 'temp');
    
    // 配置参数
    this.config = {
      memoryThreshold: 600 * 1024 * 1024, // 600MB
      logRetentionDays: 7,
      cleanupInterval: 60 * 60 * 1000, // 1小时
      gcInterval: 10 * 60 * 1000, // 10分钟
      tempFileMaxAge: 24 * 60 * 60 * 1000 // 24小时
    };
    
    this.isRunning = false;
  }

  /**
   * 启动内存优化器
   */
  start() {
    if (this.isRunning) {
      console.log('Memory optimizer is already running');
      return;
    }
    
    this.isRunning = true;
    console.log('🧠 PPH Memory Optimizer started');
    console.log(`📊 Memory threshold: ${Math.round(this.config.memoryThreshold / 1024 / 1024)}MB`);
    console.log(`🗑️ Cleanup interval: ${this.config.cleanupInterval / 1000 / 60} minutes`);
    
    // 立即执行一次清理
    this.performCleanup();
    
    // 设置定时任务
    this.cleanupTimer = setInterval(() => {
      this.performCleanup();
    }, this.config.cleanupInterval);
    
    this.gcTimer = setInterval(() => {
      this.forceGarbageCollection();
    }, this.config.gcInterval);
    
    // 监控内存使用
    this.memoryMonitorTimer = setInterval(() => {
      this.monitorMemoryUsage();
    }, 30000); // 每30秒检查一次
  }

  /**
   * 停止内存优化器
   */
  stop() {
    if (!this.isRunning) return;
    
    this.isRunning = false;
    
    if (this.cleanupTimer) clearInterval(this.cleanupTimer);
    if (this.gcTimer) clearInterval(this.gcTimer);
    if (this.memoryMonitorTimer) clearInterval(this.memoryMonitorTimer);
    
    console.log('🛑 PPH Memory Optimizer stopped');
  }

  /**
   * 执行完整清理
   */
  async performCleanup() {
    console.log('🧹 Starting cleanup process...');
    
    try {
      await this.cleanTempFiles();
      await this.cleanOldLogs();
      await this.cleanNodeModulesCache();
      await this.cleanSystemCache();
      this.forceGarbageCollection();
      
      console.log('✅ Cleanup process completed');
    } catch (error) {
      console.error('❌ Cleanup process failed:', error.message);
    }
  }

  /**
   * 清理临时文件
   */
  async cleanTempFiles() {
    try {
      if (!fs.existsSync(this.tempDir)) {
        fs.mkdirSync(this.tempDir, { recursive: true });
        return;
      }
      
      const files = fs.readdirSync(this.tempDir);
      let cleanedCount = 0;
      
      for (const file of files) {
        const filePath = path.join(this.tempDir, file);
        const stats = fs.statSync(filePath);
        const age = Date.now() - stats.mtime.getTime();
        
        if (age > this.config.tempFileMaxAge) {
          fs.unlinkSync(filePath);
          cleanedCount++;
        }
      }
      
      if (cleanedCount > 0) {
        console.log(`🗑️ Cleaned ${cleanedCount} temporary files`);
      }
    } catch (error) {
      console.error('Failed to clean temp files:', error.message);
    }
  }

  /**
   * 清理旧日志文件
   */
  async cleanOldLogs() {
    try {
      if (!fs.existsSync(this.logDir)) return;
      
      const files = fs.readdirSync(this.logDir);
      const cutoffDate = Date.now() - (this.config.logRetentionDays * 24 * 60 * 60 * 1000);
      let cleanedCount = 0;
      
      for (const file of files) {
        if (!file.endsWith('.log')) continue;
        
        const filePath = path.join(this.logDir, file);
        const stats = fs.statSync(filePath);
        
        if (stats.mtime.getTime() < cutoffDate) {
          fs.unlinkSync(filePath);
          cleanedCount++;
        }
      }
      
      if (cleanedCount > 0) {
        console.log(`📝 Cleaned ${cleanedCount} old log files`);
      }
    } catch (error) {
      console.error('Failed to clean log files:', error.message);
    }
  }

  /**
   * 清理Node.js模块缓存
   */
  async cleanNodeModulesCache() {
    try {
      // 清理require缓存中的非核心模块
      const initialCacheSize = Object.keys(require.cache).length;
      
      for (const id in require.cache) {
        // 只清理项目相关的模块，保留核心模块
        if (id.includes('node_modules') && !id.includes('core-js')) {
          delete require.cache[id];
        }
      }
      
      const finalCacheSize = Object.keys(require.cache).length;
      const cleaned = initialCacheSize - finalCacheSize;
      
      if (cleaned > 0) {
        console.log(`🧠 Cleaned ${cleaned} cached modules`);
      }
    } catch (error) {
      console.error('Failed to clean module cache:', error.message);
    }
  }

  /**
   * 清理系统缓存
   */
  async cleanSystemCache() {
    try {
      // 清理npm缓存
      await execAsync('npm cache clean --force').catch(() => {});
      
      // 清理Windows DNS缓存
      await execAsync('ipconfig /flushdns').catch(() => {});
      
      console.log('🖥️ System cache cleaned');
    } catch (error) {
      console.error('Failed to clean system cache:', error.message);
    }
  }

  /**
   * 强制垃圾回收
   */
  forceGarbageCollection() {
    try {
      if (global.gc) {
        const beforeMemory = process.memoryUsage();
        global.gc();
        const afterMemory = process.memoryUsage();
        
        const freed = beforeMemory.heapUsed - afterMemory.heapUsed;
        if (freed > 1024 * 1024) { // 只报告释放超过1MB的情况
          console.log(`♻️ Garbage collection freed ${Math.round(freed / 1024 / 1024)}MB`);
        }
      } else {
        // 如果没有启用--expose-gc，尝试其他方法
        const v8 = require('v8');
        if (v8.writeHeapSnapshot) {
          // 写入堆快照会触发垃圾回收
          const filename = path.join(this.logDir, `heap-${Date.now()}.heapsnapshot`);
          v8.writeHeapSnapshot(filename);
          // 立即删除快照文件
          setTimeout(() => {
            if (fs.existsSync(filename)) {
              fs.unlinkSync(filename);
            }
          }, 1000);
        }
      }
    } catch (error) {
      console.error('Failed to force garbage collection:', error.message);
    }
  }

  /**
   * 监控内存使用情况
   */
  async monitorMemoryUsage() {
    try {
      const memUsage = process.memoryUsage();
      const heapUsedMB = Math.round(memUsage.heapUsed / 1024 / 1024);
      const heapTotalMB = Math.round(memUsage.heapTotal / 1024 / 1024);
      const rssMB = Math.round(memUsage.rss / 1024 / 1024);
      
      // 检查是否超过阈值
      if (memUsage.heapUsed > this.config.memoryThreshold) {
        console.log(`⚠️ High memory usage detected: ${heapUsedMB}MB (threshold: ${Math.round(this.config.memoryThreshold / 1024 / 1024)}MB)`);
        
        // 执行紧急清理
        await this.performEmergencyCleanup();
      }
      
      // 每5分钟报告一次内存状态
      if (Date.now() % (5 * 60 * 1000) < 30000) {
        console.log(`📊 Memory usage: Heap ${heapUsedMB}/${heapTotalMB}MB, RSS ${rssMB}MB`);
      }
    } catch (error) {
      console.error('Failed to monitor memory usage:', error.message);
    }
  }

  /**
   * 紧急内存清理
   */
  async performEmergencyCleanup() {
    console.log('🚨 Performing emergency memory cleanup...');
    
    try {
      // 强制垃圾回收
      this.forceGarbageCollection();
      
      // 清理所有缓存
      await this.cleanNodeModulesCache();
      await this.cleanTempFiles();
      
      // 再次强制垃圾回收
      setTimeout(() => {
        this.forceGarbageCollection();
      }, 1000);
      
      console.log('✅ Emergency cleanup completed');
    } catch (error) {
      console.error('❌ Emergency cleanup failed:', error.message);
    }
  }

  /**
   * 获取内存使用报告
   */
  getMemoryReport() {
    const memUsage = process.memoryUsage();
    
    return {
      heapUsed: Math.round(memUsage.heapUsed / 1024 / 1024),
      heapTotal: Math.round(memUsage.heapTotal / 1024 / 1024),
      rss: Math.round(memUsage.rss / 1024 / 1024),
      external: Math.round(memUsage.external / 1024 / 1024),
      threshold: Math.round(this.config.memoryThreshold / 1024 / 1024),
      isOptimizing: this.isRunning
    };
  }
}

// 如果直接运行此脚本
if (require.main === module || process.env.pm_id !== undefined || process.env.PM2_HOME) {
  const optimizer = new MemoryOptimizer();

  // 防止PM2误判：先输出启动信息
  console.log('🚀 PPH Memory Optimizer initializing...');

  // 延迟启动，确保PM2识别为稳定进程
  setTimeout(() => {
    optimizer.start();
    console.log('✅ PPH Memory Optimizer fully started');
  }, 1000);
  
  // 优雅关闭 - 添加延迟防止PM2误判
  process.on('SIGINT', () => {
    console.log('\n🛑 Received SIGINT, shutting down memory optimizer...');
    setTimeout(() => {
      optimizer.stop();
      process.exit(0);
    }, 2000); // 延迟2秒关闭
  });

  process.on('SIGTERM', () => {
    console.log('\n🛑 Received SIGTERM, shutting down...');
    setTimeout(() => {
      optimizer.stop();
      process.exit(0);
    }, 2000); // 延迟2秒关闭
  });
  
  // 保持进程运行
  console.log('Memory optimizer is running. Press Ctrl+C to stop.');
}

module.exports = MemoryOptimizer;
